#include <GL/freeglut.h>

GLint winWidth = 600, winHeight = 600;

/* 观察坐标系参数设置 */
GLfloat x0 = 0, y0 = 0, z0 = -5;      // 设置观察坐标系原点
GLfloat xref = 0, yref = 0, zref = 0; // 设置观察坐标系参考点（视点）
GLfloat Vx = 0, Vy = 1, Vz = 0;       // 设置观察坐标系向上向量（up向量，也就是y轴正方向）

/* 观察体参数设置 */
GLfloat xwMin = -1, ywMin = -1, xwMax = 1, ywMax = 1; // 设置裁剪窗口坐标范围
GLfloat dnear = 1.5, dfar = 20;                       // 设置近、远裁剪面深度范围

void init()
{
    // 深度测试为什么不好使？不能针对solid做？
    //
    // glClearDepth(GL_DEPTH_BUFFER_BIT);
    // glEnable(GL_DEPTH_TEST);
    glClearColor(1, 1, 1, 0);
    // glEnable(GL_DEPTH_BUFFER_BIT);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDepthFunc(GL_LESS);
    /* ①观察变换 */
    gluLookAt(x0, y0, z0, xref, yref, zref, Vx, Vy, Vz); // 三维观察参数
    /* 模型变换 */
    glMatrixMode(GL_MODELVIEW);
    glScalef(2, 2, 2);
    glRotatef(45, 0, 1, 1);
    /* ②投影变换 */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    /* 透视投影 */
    glFrustum(xwMin, xwMax, ywMin, ywMax, dnear, dfar); // 设置frustum
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0, 1, 0); // 前景色为绿色
    glutSolidCube(1);   // 绘制单位立方体实体
    glColor3f(0, 0, 0); // 前景色为黑色
    glLineWidth(2);     // 线宽为2px
    glutWireCube(1);    // 绘制单位立方体线框

    glFlush();
}

void reshape(GLint newWidth, GLint newHeight)
{
    /* ③视口变换 */
    glViewport(0, 0, newWidth, newHeight); // 视口大小
    winWidth = newWidth;
    winHeight = newHeight;
}

void main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(winWidth, winHeight);
    glutCreateWindow("单位立方体的透视投影");

    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
}
